package com.SNQ.project.English_speaking_learning_system.config;

import java.net.URL;

import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizer;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerListener;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerResponse;
import java.io.InputStream;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONArray;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 此示例演示了
 *      ASR一句话识别API调用
 *      通过本地文件模拟实时流发送
 *      识别耗时计算
 * (仅作演示，需用户根据实际情况实现)
 */
public class SpeechRecognizerDemo {
    private static final Logger logger = LoggerFactory.getLogger(SpeechRecognizerDemo.class);
    private String appKey;
    NlsClient client;

    public SpeechRecognizerDemo(String appKey, String token, String url) {
        this.appKey = appKey;
        //TODO 重要提示 创建NlsClient实例,应用全局创建一个即可,生命周期可和整个应用保持一致,默认服务地址为阿里云线上服务地址
        if(url.isEmpty()) {
            client = new NlsClient(token);
        }else {
            client = new NlsClient(url, token);
        }
    }

    /// 根据二进制数据大小计算对应的同等语音长度
    /// sampleRate 仅支持8000或16000
    public static int getSleepDelta(int dataSize, int sampleRate) {
        // 仅支持16位采样
        int sampleBytes = 16;
        // 仅支持单通道
        int soundChannel = 1;
        return (dataSize * 10 * 8000) / (160 * sampleRate);
    }

    private class MySpeechRecognizerListener extends SpeechRecognizerListener {
        private StringBuilder recognizedText = new StringBuilder();

        // 识别结果部分内容的回调函数
        @Override
        public void onRecognitionResultChanged(SpeechRecognizerResponse speechRecognizerResponse) {
            // 监听到中间结果时
            recognizedText.append(speechRecognizerResponse.getRecognizedText()); // 记录中间结果
        }

        @Override
        public void onRecognitionCompleted(SpeechRecognizerResponse speechRecognizerResponse) {
            // 监听到最终结果时
            recognizedText.append(speechRecognizerResponse.getRecognizedText()); // 记录最终结果
        }

        @Override
        public void onStarted(SpeechRecognizerResponse speechRecognizerResponse) {

        }

        @Override
        public void onFail(SpeechRecognizerResponse speechRecognizerResponse) {

        }

        public String getRecognizedText() {
            return recognizedText.toString();
        }

    }

    private SpeechRecognizerListener getRecognizerListener(int myOrder, String myParam) {
        return new MySpeechRecognizerListener();
    }


    public String process(String urlPath, int sampleRate) {
        SpeechRecognizer recognizer = null;
        MySpeechRecognizerListener listener = null;
        try {
            // 传递用户自定义参数
            String myParam = "user-param";
            int myOrder = 1234;

            // 使用自定义的 listener 存储识别结果
            listener = new MySpeechRecognizerListener();

            recognizer = new SpeechRecognizer(client, listener);
            recognizer.setAppKey(appKey);

            //设置音频编码格式 TODO 如果是opus文件，请设置为 InputFormatEnum.OPUS
            recognizer.setFormat(InputFormatEnum.WAV);
            //设置音频采样率
            if(sampleRate == 16000) {
                recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
            } else if(sampleRate == 8000) {
                recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_8K);
            }
            //设置是否返回中间识别结果
            recognizer.setEnableIntermediateResult(true);

            //此方法将以上参数设置序列化为json发送给服务端,并等待服务端确认
            long now = System.currentTimeMillis();
            recognizer.start();
            logger.info("ASR start latency : " + (System.currentTimeMillis() - now) + " ms");

            // 使用 URL 读取音频数据
            URL url = new URL(urlPath);
            try (InputStream inputStream = url.openStream()) {
                byte[] buffer = new byte[3200];
                int len;
                while ((len = inputStream.read(buffer)) > 0) {
                    logger.info("send data pack length: " + len);
                    recognizer.send(buffer, len);

                    int deltaSleep = getSleepDelta(len, sampleRate);
                    Thread.sleep(deltaSleep);
                }
            }

            logger.info("ASR wait for complete");
            recognizer.stop();
            logger.info("ASR stop latency : " + (System.currentTimeMillis() - now) + " ms");

        } catch (Exception e) {
            System.err.println(e.getMessage());
        } finally {
            //关闭连接
            if (null != recognizer) {
                recognizer.close();
            }
        }

        // 返回识别的结果文本
        if (listener != null) {
            return listener.getRecognizedText();
        } else {
            return "";
        }
    }

    public void shutdown() {
        client.shutdown();
    }

    public static String main(String audiourl) throws Exception {
        String appKey = "qssOrMYvh5zbgYu1";
        String token = "b6d09573efa34822a677f5533f998673";
        String url = "wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1"; // 默认即可，默认值：wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1


        SpeechRecognizerDemo demo = new SpeechRecognizerDemo(appKey, token, url);
        // TODO 重要提示： 这里用一个本地文件来模拟发送实时流数据，实际使用时，用户可以从某处实时采集或接收语音流并发送到ASR服务端
        String content = demo.process(audiourl, 16000);
        //demo.process("./nls-sample.opus", 16000);
        demo.shutdown();
        return content;
    }
}
